package com.jxm.websocket.ws.config;

import com.alibaba.fastjson2.JSON;
import com.jxm.websocket.ws.entity.Message;
import com.jxm.websocket.ws.utils.MessageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: jxm
 * @Description: 建立一个连接就是建一个对象
 * @Date: 2023/7/4 10:25
 * @Version: 1.0
 */
@Slf4j
@Component
@ServerEndpoint(value = "/chat",configurator = GetHttpSessionConfiguration.class)
public class WebsocketApi {

    //用来实现服务端与指定客户端通信的话，可以使用Map来存放当前在线用户，其中Key可以为用户标识
    public static ConcurrentHashMap<String,WebsocketApi> onlineWebSocketMap = new ConcurrentHashMap<>();

    //每一个webSocket对象持有session对象，通过该对象可以发送消息给指定的用户
    private Session session;

    //声明一个HttpSession对象，我们之前在HttpSession对象中存储了用户名
    private HttpSession httpSession;

    /**
     * 客户端和服务端建立连接
     */
    @OnOpen
    public void onOpen(Session session,EndpointConfig config){
        log.info("进入连接");
        this.session = session;
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        this.httpSession = httpSession;
        //将当前对象存储到容器中
        onlineWebSocketMap.put((String) httpSession.getAttribute("user"),this);
        //将当前在线用户名推送给所有客户端
        String message = MessageUtil.getMessage(true, null, getNames());
        //广播消息
        broadcastAllUsers(message);
        log.info("websocket消息: 有新的连接，总数为:" + onlineWebSocketMap.size());
    }

    //接收消息（用户之间的信息发送）
    @OnMessage
    public void onMessage(String message){
        log.info("接收到客户端消息");
        //接受到客户端消息
        Message msg = JSON.parseObject(message, Message.class);
        //接收方
        String toName = msg.getToName();
        //消息内容
        String data = msg.getMessage();
        //当前用户
        String currentName = (String) httpSession.getAttribute("user");

        String resultMsg = MessageUtil.getMessage(false, currentName, data);
        //发送数据
        WebsocketApi websocketApi = onlineWebSocketMap.get(toName);
        try {
            websocketApi.session.getBasicRemote().sendText(resultMsg);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //断开连接
    @OnClose
    public void onClose(){
        log.info("断开连接");
        onlineWebSocketMap.remove(httpSession.getAttribute("user"));
        //广播 将当前在线用户用户名推送给客户端
        broadcastAllUsers(MessageUtil.getMessage(true,null,getNames()));
    }

    //连接错误
    @OnError
    public void onError(Throwable error){
        log.error("连接错误"+error.getMessage());
    }

    /**
     * 广播 推送给所有客户端
     * @param message
     */
    private void broadcastAllUsers(String message) {
        Set<String> names = onlineWebSocketMap.keySet();
        //要将该消息推送给每个的客户端
        for (String name : names) {
            WebsocketApi websocketApi = onlineWebSocketMap.get(name);
            try {
                //推送给客户端
                websocketApi.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取所有在线用户名
     * @return
     */
    private Set<String> getNames() {
        return onlineWebSocketMap.keySet();
    }

}
